#pragma once

typedef unsigned __int32 bitboard;

class BitboardUtils {
public:
	static void Print(bitboard bb);

	static inline bitboard ClearBit(bitboard original, int bit);

	static inline char TestBit(bitboard* bb, int bit);
	static char TestBitAndSet(bitboard* bb, int bit);
	static char TestBitAndReset(bitboard* bb, int bit);

	static char BitScanForward(bitboard bb, int* position);
	static int BitsCount(bitboard bb);
private:
	static char At(bitboard* bb, int position);
};

// -----------
// Definuje bitovych masek pro jednotliva pole hraci plochy
const bitboard B8 = 0x1;
const bitboard D8 = 0x2;
const bitboard F8 = 0x4;
const bitboard H8 = 0x8;

const bitboard A7 = 0x10;
const bitboard C7 = 0x20;
const bitboard E7 = 0x40;
const bitboard G7 = 0x80;

const bitboard B6 = 0x100;
const bitboard D6 = 0x200;
const bitboard F6 = 0x400;
const bitboard H6 = 0x800;

const bitboard A5 = 0x1000;
const bitboard C5 = 0x2000;
const bitboard E5 = 0x4000;
const bitboard G5 = 0x8000;

const bitboard B4 = 0x10000;
const bitboard D4 = 0x20000;
const bitboard F4 = 0x40000;
const bitboard H4 = 0x80000;

const bitboard A3 = 0x100000;
const bitboard C3 = 0x200000;
const bitboard E3 = 0x400000;
const bitboard G3 = 0x800000;

const bitboard B2 = 0x1000000;
const bitboard D2 = 0x2000000;
const bitboard F2 = 0x4000000;
const bitboard H2 = 0x8000000;

const bitboard A1 = 0x10000000;
const bitboard C1 = 0x20000000;
const bitboard E1 = 0x40000000;
const bitboard G1 = 0x80000000;

// -----------
// Definuje pole bitovych masek pro sloupce hraci plochy
const bitboard ColumnsMasks[8] = {
A1 | A3 | A5 | A7,
B2 | B4 | B6 | B8,
C1 | C3 | C5 | C7,
D2 | D4 | D6 | D8,
E1 | E3 | E5 | E7,
F2 | F4 | F6 | F8,
G1 | G3 | G5 | G7,
H2 | H4 | H6 | H8
};

// -----------
// Definuje pole bitovych masek pro radky hraci plochy
const bitboard RowsMasks[8] = {
B8 | D8 | F8 | H8,
A7 | C7 | E7 | G7,
B6 | D6 | F6 | H6,
A5 | C5 | E5 | G5,
B4 | D4 | F4 | H4,
A3 | C3 | E3 | G3,
B2 | D2 | F2 | H2,
A1 | C1 | E1 | G1
};

// -----------
// Definuje pole bitovych masek pro jednotliva pole hraci plochy
const bitboard FieldsMasks[32] = {
B8 , D8 , F8 , H8,
A7 , C7 , E7 , G7,
B6 , D6 , F6 , H6,
A5 , C5 , E5 , G5,
B4 , D4 , F4 , H4,
A3 , C3 , E3 , G3,
B2 , D2 , F2 , H2,
A1 , C1 , E1 , G1
};

// -----------
// Definuje pole bitovych masek pro jednoduchy pohyb hracich kamenu z daneho pole v danem smeru
// Prvni index definuje smer - 0: nahoru doleva; 1 : nahoru doprava; 2: dolu doprava; 3: dolu doleva
// Druhy index definuje pole ze ktereho se kamen pohybuje
// bitboard s temito indexy obsahuje definuje pole na jake se muze kamen dostat
const bitboard MovesMasks[4][32] = {
	{
		0x0,					0x0,					0x0,					0x0,
		0x0,					0x1,					0x2,					0x4,
		0x10,					0x20,					0x40,					0x80,
		0x0,					0x100,				0x200,				0x400,
		0x1000,				0x2000,				0x4000,				0x8000,
		0x0,					0x10000,			0x20000,			0x40000,
		0x100000,			0x200000,			0x400000,			0x800000,
		0x0,					0x1000000,		0x2000000,		0x4000000
	},
	{
		0x0,					0x0,					0x0,					0x0,
		0x1,					0x2,					0x4,					0x8,
		0x20,					0x40,					0x80,					0x0,
		0x100,				0x200,				0x400,				0x800,
		0x2000,				0x4000,				0x8000,				0x0,
		0x10000,			0x20000,			0x40000,			0x80000,
		0x200000,			0x400000,			0x800000,			0x0,
		0x1000000,		0x2000000,		0x4000000,		0x8000000
	},
	{
		0x20,					0x40,					0x80,					0x0,
		0x100,				0x200,				0x400,				0x800,
		0x2000,				0x4000,				0x8000,				0x0,
		0x10000,			0x20000,			0x40000,			0x80000,
		0x200000,			0x400000,			0x800000,			0x0,
		0x1000000,		0x2000000,		0x4000000,		0x8000000,
		0x20000000,		0x40000000,		0x80000000,		0x0,
		0x0,					0x0,					0x0,					0x0
	},
	{
		0x10,					0x20,					0x40,					0x80,
		0x0,					0x100,				0x200,				0x400,
		0x1000,				0x2000,				0x4000,				0x8000,
		0x0,					0x10000,			0x20000,			0x40000,
		0x100000,			0x200000,			0x400000,			0x800000,
		0x0,					0x1000000,		0x2000000,		0x4000000,
		0x10000000,		0x20000000,		0x40000000,		0x80000000,
		0x0,					0x0,					0x0,					0x0
	}
};

// -----------
// Definuje pole bitovych masek pro pohyb kamenu s preskokem z daneho pole v danem smeru
// Prvni index definuje smer - 0: nahoru doleva; 1 : nahoru doprava; 2: dolu doprava; 3: dolu doleva
// Druhy index definuje pole ze ktereho se kamen pohybuje
// bitboard s temito indexy obsahuje definuje pole na jake se muze kamen dostat pri preskoku souperova kamene
const bitboard JumpsMasks[4][32] = {
	{
		0x0,					0x0,					0x0,					0x0,
		0x0,					0x0,					0x0,					0x0,
		0x0,					0x1,					0x2,					0x4,
		0x0,					0x10,					0x20,					0x40,
		0x0,					0x100,				0x200,				0x400,
		0x0,					0x1000,				0x2000,				0x4000,
		0x0,					0x10000,			0x20000,			0x40000,
		0x0,					0x100000,			0x200000,			0x400000
	},
	{
		0x0,					0x0,					0x0,					0x0,
		0x0,					0x0,					0x0,					0x0,
		0x2,					0x4,					0x8,					0x0,
		0x20,					0x40,					0x80,					0x0,
		0x200,				0x400,				0x800,				0x0,
		0x2000,				0x4000,				0x8000,				0x0,
		0x20000,			0x40000,			0x80000,			0x0,
		0x200000,			0x400000,			0x800000,			0x0
	},
	{
		0x200,				0x400,				0x800,				0x0,
		0x2000,				0x4000,				0x8000,				0x0,
		0x20000,			0x40000,			0x80000,			0x0,
		0x200000,			0x400000,			0x800000,			0x0,
		0x2000000,		0x4000000,		0x8000000,		0x0,
		0x20000000,		0x40000000,		0x80000000,		0x0,
		0x0,					0x0,					0x0,					0x0,
		0x0,					0x0,					0x0,					0x0
	},
	{
		0x0,					0x100,				0x200,				0x400,
		0x0,					0x1000,				0x2000,				0x4000,
		0x0,					0x10000,			0x20000,			0x40000,
		0x0,					0x100000,			0x200000,			0x400000,
		0x0,					0x1000000,		0x2000000,		0x4000000,
		0x0,					0x10000000,		0x20000000,		0x40000000,
		0x0,					0x0,					0x0,					0x0,
		0x0,					0x0,					0x0,					0x0
	}
};
